import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { PlayerTank } from './PlayerTank';
import { EnemyTank } from './EnemyTank';
import { Terrain } from './Terrain';
import { Projectile } from './Projectile';
import { PowerUp } from './PowerUp';
import { Explosion } from './Explosion';
import { PhysicsWorld } from '../utils/PhysicsWorld';
import { PerformanceMonitor } from '../utils/PerformanceMonitor';
import { Debug } from '../utils/Debug';

// 游戏回调接口
interface GameCallbacks {
  onScoreChange: (score: number) => void;
  onHealthChange: (health: number) => void;
  onGameOver: (finalScore: number) => void;
}

// 游戏选项接口
interface GameOptions {
  debug?: boolean;
  showPerformance?: boolean;
}

export class Game {
  // Three.js 相关
  private renderer: THREE.WebGLRenderer;
  private scene: THREE.Scene;
  private camera: THREE.PerspectiveCamera;
  private cameraTarget: THREE.Vector3 = new THREE.Vector3();
  private controls: OrbitControls | null = null;
  private clock: THREE.Clock;
  
  // 游戏对象
  private playerTank: PlayerTank | null = null;
  private enemyTanks: EnemyTank[] = [];
  private projectiles: Projectile[] = [];
  private explosions: Explosion[] = [];
  private powerUps: PowerUp[] = [];
  private terrain: Terrain | null = null;
  
  // 游戏状态
  private score: number = 0;
  private isGameOver: boolean = false;
  private isInitialized: boolean = false;
  private enemySpawnTimer: number = 0;
  private powerUpSpawnTimer: number = 0;
  private physics: PhysicsWorld;
  
  // 加载管理器和回调
  private loadingManager: THREE.LoadingManager;
  private callbacks: GameCallbacks;
  
  private performanceMonitor: PerformanceMonitor | null = null;
  private isDebugMode: boolean = false;
  private animationFrameId: number | null = null;
  
  constructor(
    loadingManager: THREE.LoadingManager, 
    callbacks: GameCallbacks,
    options: GameOptions = {}
  ) {
    Debug.log('初始化游戏实例');
    
    this.loadingManager = loadingManager;
    this.callbacks = callbacks;
    this.clock = new THREE.Clock();
    
    // 初始化性能监控器
    if (options.showPerformance) {
      this.performanceMonitor = new PerformanceMonitor();
      this.performanceMonitor.enable();
    }
    
    // 设置调试模式
    this.isDebugMode = options.debug || false;
    
    try {
      // 初始化渲染器
      this.renderer = new THREE.WebGLRenderer({ 
        antialias: true,
        powerPreference: 'high-performance',
        alpha: false,
        stencil: false
      });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // 限制像素比以提高性能
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      document.body.appendChild(this.renderer.domElement);
      Debug.log('渲染器初始化完成');
      
      // 初始化场景
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0x87CEEB); // 天蓝色背景
      this.scene.fog = new THREE.Fog(0x87CEEB, 20, 100);
      Debug.log('场景初始化完成');
      
      // 初始化相机
      this.camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
      this.camera.position.set(0, 20, 20);
      this.camera.lookAt(this.cameraTarget);
      Debug.log('相机初始化完成');
      
      // 初始化轨道控制器（仅用于调试）
      if (this.isDebugMode) {
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.enableDamping = true;
        this.controls.dampingFactor = 0.05;
        this.controls.maxPolarAngle = Math.PI / 2 - 0.1; // 限制相机角度，不能看到地面以下
      }
      Debug.log('控制器初始化完成');
      
      // 初始化物理世界
      this.physics = new PhysicsWorld();
      Debug.log('物理世界初始化完成');
      
      // 设置光照
      this.setupLights();
      Debug.log('光照设置完成');
      
      // 加载游戏资源
      this.loadGameAssets();
      
      this.isInitialized = true;
      Debug.log('游戏实例初始化完成');
      
    } catch (error) {
      Debug.error(`游戏初始化失败: ${error}`);
      throw new Error(`游戏初始化失败: ${error}`);
    }
  }
  
  private setupLights(): void {
    try {
      // 环境光
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
      this.scene.add(ambientLight);
      
      // 定向光（模拟太阳光）
      const sunLight = new THREE.DirectionalLight(0xffffff, 1);
      sunLight.position.set(50, 100, 50);
      sunLight.castShadow = true;
      
      // 设置阴影属性
      sunLight.shadow.mapSize.width = 1024; // 减小阴影贴图尺寸以提高性能
      sunLight.shadow.mapSize.height = 1024;
      sunLight.shadow.camera.near = 0.5;
      sunLight.shadow.camera.far = 500;
      sunLight.shadow.camera.left = -50;
      sunLight.shadow.camera.right = 50;
      sunLight.shadow.camera.top = 50;
      sunLight.shadow.camera.bottom = -50;
      
      this.scene.add(sunLight);
      Debug.log('灯光设置完成');
    } catch (error) {
      Debug.error(`设置光照时出错: ${error}`);
    }
  }
  
  private loadGameAssets(): void {
    try {
      Debug.log('开始加载游戏资源');
      
      // 加载地形
      Debug.log('加载地形');
      this.terrain = new Terrain(this.scene, this.physics, this.loadingManager);
      
      // 加载玩家坦克
      Debug.log('加载玩家坦克');
      this.playerTank = new PlayerTank(
        this.scene,
        this.physics,
        this.loadingManager,
        (projectile: Projectile) => this.projectiles.push(projectile),
        (health: number) => {
          this.callbacks.onHealthChange(health);
          if (health <= 0 && !this.isGameOver) {
            this.gameOver();
          }
        }
      );
      
      Debug.log('游戏资源加载完成');
    } catch (error) {
      Debug.error(`加载游戏资源时出错: ${error}`);
      // 即使加载失败，我们仍然继续，以便用户可以看到某些内容
    }
  }
  
  public start(): void {
    try {
      Debug.log('开始游戏');
      
      if (!this.isInitialized) {
        Debug.error('游戏未完全初始化，但仍尝试启动');
      }
      
      // 重置游戏状态
      this.score = 0;
      this.isGameOver = false;
      this.callbacks.onScoreChange(this.score);
      
      if (this.playerTank) {
        this.playerTank.reset();
        this.callbacks.onHealthChange(this.playerTank.getHealth());
      } else {
        Debug.warn('玩家坦克未初始化');
        // 尝试再次创建玩家坦克
        try {
          this.playerTank = new PlayerTank(
            this.scene,
            this.physics,
            this.loadingManager,
            (projectile: Projectile) => this.projectiles.push(projectile),
            (health: number) => {
              this.callbacks.onHealthChange(health);
              if (health <= 0 && !this.isGameOver) {
                this.gameOver();
              }
            }
          );
          this.callbacks.onHealthChange(this.playerTank.getHealth());
        } catch (error) {
          Debug.error(`无法创建玩家坦克: ${error}`);
        }
      }
      
      // 清除旧的敌人和投射物
      this.clearEntities();
      
      // 开始游戏循环
      this.clock.start();
      this.animate();
      
      Debug.log('游戏循环已开始');
    } catch (error) {
      Debug.error(`启动游戏时出错: ${error}`);
    }
  }
  
  public restart(): void {
    Debug.log('重新开始游戏');
    this.start();
  }
  
  private clearEntities(): void {
    try {
      // 移除所有敌人坦克
      for (const enemy of this.enemyTanks) {
        enemy.dispose();
      }
      this.enemyTanks = [];
      
      // 移除所有投射物
      for (const projectile of this.projectiles) {
        projectile.dispose();
      }
      this.projectiles = [];
      
      // 移除所有爆炸效果
      for (const explosion of this.explosions) {
        explosion.dispose();
      }
      this.explosions = [];
      
      // 移除所有能量补给
      for (const powerUp of this.powerUps) {
        powerUp.dispose();
      }
      this.powerUps = [];
      
      Debug.log('所有实体已清除');
    } catch (error) {
      Debug.error(`清除实体时出错: ${error}`);
    }
  }
  
  private spawnEnemy(): void {
    try {
      if (this.enemyTanks.length >= 5) return; // 限制最大敌人数量
      
      // 在地图边缘随机位置生成敌人
      const mapSize = 40;
      
      // 随机选择地图边缘的一个点
      const spawnSide = Math.floor(Math.random() * 4); // 0:上, 1:右, 2:下, 3:左
      const rand = Math.random() * mapSize - mapSize / 2;
      let x = 0;
      let z = 0;
      
      switch (spawnSide) {
        case 0: // 上边缘
          x = rand;
          z = -mapSize / 2 + 5; // 稍微远离边界
          break;
        case 1: // 右边缘
          x = mapSize / 2 - 5; // 稍微远离边界
          z = rand;
          break;
        case 2: // 下边缘
          x = rand;
          z = mapSize / 2 - 5; // 稍微远离边界
          break;
        case 3: // 左边缘
          x = -mapSize / 2 + 5; // 稍微远离边界
          z = rand;
          break;
      }
      
      // 创建一个THREE.Vector3对象
      const spawnPosition = new THREE.Vector3(x, 0.5, z);
      
      // 确保生成位置与玩家保持一定距离
      if (this.playerTank) {
        const playerPos = this.playerTank.getPosition();
        const distToPlayer = spawnPosition.distanceTo(playerPos);
        
        if (distToPlayer < 15) {
          // 太近了，取消生成
          Debug.log('敌人生成位置太靠近玩家，取消生成');
          return;
        }
      }
      
      Debug.log(`尝试在位置 (${x.toFixed(1)}, 0.5, ${z.toFixed(1)}) 生成敌人坦克`);
      
      // 创建敌人坦克
      const enemy = new EnemyTank(
        this.scene,
        this.physics,
        this.loadingManager,
        spawnPosition, // 确保传递的是THREE.Vector3对象
        (projectile: Projectile) => this.projectiles.push(projectile),
        () => {
          // 敌人被摧毁时的回调
          this.score += 100;
          this.callbacks.onScoreChange(this.score);
          
          // 有几率掉落能量补给
          if (Math.random() < 0.3) {
            this.spawnPowerUp(enemy.getPosition());
          }
        }
      );
      
      this.enemyTanks.push(enemy);
      Debug.log(`成功生成敌方坦克，当前敌人数量: ${this.enemyTanks.length}`);
    } catch (error) {
      Debug.error(`生成敌人时出错: ${error}`);
    }
  }
  
  private spawnPowerUp(position: THREE.Vector3 | { x: number, y: number, z: number }): void {
    try {
      // 确保position是一个THREE.Vector3对象
      let powerUpPosition: THREE.Vector3;
      
      if (position instanceof THREE.Vector3) {
        powerUpPosition = position.clone();
      } else if (position && typeof position.x === 'number' && typeof position.y === 'number' && typeof position.z === 'number') {
        powerUpPosition = new THREE.Vector3(position.x, position.y, position.z);
      } else {
        // 如果没有有效位置，在随机位置生成
        const mapSize = 40;
        const x = (Math.random() - 0.5) * (mapSize - 10);
        const z = (Math.random() - 0.5) * (mapSize - 10);
        powerUpPosition = new THREE.Vector3(x, 0.5, z);
      }
      
      Debug.log(`在位置 (${powerUpPosition.x.toFixed(1)}, ${powerUpPosition.y.toFixed(1)}, ${powerUpPosition.z.toFixed(1)}) 生成能量补给`);
      
      const powerUp = new PowerUp(
        this.scene,
        this.physics,
        this.loadingManager,
        powerUpPosition, // 确保传递的是THREE.Vector3对象
        () => {
          // 玩家收集到能量补给的回调
          if (this.playerTank) {
            // 随机选择一种提升效果
            const effect = Math.floor(Math.random() * 3);
            switch (effect) {
              case 0: // 恢复生命值
                this.playerTank.heal(25);
                this.callbacks.onHealthChange(this.playerTank.getHealth());
                Debug.log('玩家获得生命值提升');
                break;
              case 1: // 临时提升速度
                this.playerTank.boostSpeed(5000); // 5秒速度提升
                Debug.log('玩家获得速度提升');
                break;
              case 2: // 临时提升火力
                this.playerTank.boostFirepower(5000); // 5秒火力提升
                Debug.log('玩家获得火力提升');
                break;
            }
          }
        }
      );
      
      this.powerUps.push(powerUp);
      Debug.log('能量补给生成成功');
    } catch (error) {
      Debug.error(`生成能量补给时出错: ${error}`);
    }
  }
  
  private createExplosion(position: THREE.Vector3, size: number = 1): void {
    const explosion = new Explosion(this.scene, position, size);
    this.explosions.push(explosion);
  }
  
  private update(deltaTime: number): void {
    if (this.isGameOver) return;
    
    try {
      // 更新物理世界
      this.physics.update(deltaTime);
      
      // 更新玩家坦克
      if (this.playerTank && this.playerTank.isAlive()) {
        this.playerTank.update(deltaTime);
        
        // 更新相机位置跟随玩家
        const playerPos = this.playerTank.getPosition();
        this.cameraTarget.copy(playerPos);
        
        // 第三人称跟随相机 - 固定在玩家后方，不随旋转移动
        const idealOffset = new THREE.Vector3(0, 15, 15);
        const idealLookAt = new THREE.Vector3(0, 0, -10);
        
        // 注释掉以下代码，避免相机随坦克旋转
        // const tankRotation = this.playerTank.getRotation();
        // idealOffset.applyAxisAngle(new THREE.Vector3(0, 1, 0), tankRotation);
        // idealLookAt.applyAxisAngle(new THREE.Vector3(0, 1, 0), tankRotation);
        
        // 设置相机位置固定在玩家后上方，不随旋转而变化
        const smoothFactor = 0.05; // 平滑因子
        const targetPosition = new THREE.Vector3(
          playerPos.x,
          playerPos.y + idealOffset.y,
          playerPos.z + idealOffset.z
        );
        this.camera.position.lerp(targetPosition, smoothFactor);
        
        // 相机始终看向玩家位置
        this.camera.lookAt(playerPos);
      }
      
      // 更新敌人坦克
      for (let i = this.enemyTanks.length - 1; i >= 0; i--) {
        const enemy = this.enemyTanks[i];
        
        // 获取玩家位置作为目标
        const targetPosition = this.playerTank ? this.playerTank.getPosition() : undefined;
        
        // 如果敌人不再活跃，从数组中移除
        if (!enemy.update(deltaTime, targetPosition)) {
          enemy.dispose();
          this.enemyTanks.splice(i, 1);
        }
      }
      
      // 更新投射物
      for (let i = this.projectiles.length - 1; i >= 0; i--) {
        const projectile = this.projectiles[i];
        projectile.update(deltaTime);
        
        // 如果投射物已经过期，从数组中移除
        if (!projectile.isActive()) {
          projectile.dispose();
          this.projectiles.splice(i, 1);
          continue;
        }
        
        // 检测投射物与坦克的碰撞
        if (projectile.getSource() === 'player') {
          // 玩家的投射物检测与敌人的碰撞
          for (const enemy of this.enemyTanks) {
            if (enemy.isAlive() && this.physics.checkCollision(
              projectile.getPosition(), 
              projectile.getRadius(), 
              'enemy',
              false
            )) {
              enemy.takeDamage(projectile.getDamage());
              this.createExplosion(projectile.getPosition(), 1);
              projectile.dispose();
              this.projectiles.splice(i, 1);
              break;
            }
          }
        } else if (projectile.getSource() === 'enemy' && this.playerTank && this.playerTank.isAlive()) {
          // 敌人的投射物检测与玩家的碰撞
          if (this.physics.checkCollision(
            projectile.getPosition(), 
            projectile.getRadius(), 
            'player',
            false
          )) {
            this.playerTank.takeDamage(projectile.getDamage());
            this.createExplosion(projectile.getPosition(), 1);
            projectile.dispose();
            this.projectiles.splice(i, 1);
          }
        }
      }
      
      // 更新爆炸效果
      for (let i = this.explosions.length - 1; i >= 0; i--) {
        const explosion = this.explosions[i];
        explosion.update(deltaTime);
        
        // 如果爆炸效果已完成，从数组中移除
        if (explosion.isFinished()) {
          explosion.dispose();
          this.explosions.splice(i, 1);
        }
      }
      
      // 更新能量补给
      for (let i = this.powerUps.length - 1; i >= 0; i--) {
        const powerUp = this.powerUps[i];
        powerUp.update(deltaTime);
        
        // 检测玩家是否收集到能量补给
        if (this.playerTank && this.playerTank.isAlive() && 
            this.physics.checkCollision(this.playerTank.getPosition(), 1.0, 'power-up')) {
          // 应用能量补给效果
          const type = powerUp.getType();
          const amount = powerUp.getAmount();
          
          // 根据类型应用不同效果
          switch (type) {
            case 'health':
              this.playerTank.heal(amount);
              break;
            case 'energy':
              this.playerTank.addEnergy(amount);
              break;
            case 'speed':
              this.playerTank.boostSpeed();
              break;
            case 'firepower':
              this.playerTank.boostFirepower();
              break;
          }
          
          // 从数组中移除
          powerUp.dispose();
          this.powerUps.splice(i, 1);
        }
        
        // 如果能量补给已经过期，从数组中移除
        if (!powerUp.isActive()) {
          powerUp.dispose();
          this.powerUps.splice(i, 1);
        }
      }
      
      // 更新敌人生成计时器
      this.enemySpawnTimer -= deltaTime;
      if (this.enemySpawnTimer <= 0) {
        this.spawnEnemy();
        this.enemySpawnTimer = 3 + Math.random() * 2; // 每3-5秒生成一个敌人
      }
      
      // 更新能量补给生成计时器
      this.powerUpSpawnTimer -= deltaTime;
      if (this.powerUpSpawnTimer <= 0) {
        // 在随机位置生成能量补给
        const position = new THREE.Vector3(
          (Math.random() - 0.5) * 40,
          0.5, // 确保y坐标是有效值
          (Math.random() - 0.5) * 40
        );
        this.spawnPowerUp(position);
        this.powerUpSpawnTimer = 10 + Math.random() * 5; // 每10-15秒生成一个能量补给
      }
    } catch (error) {
      Debug.error(`游戏更新过程中出错: ${error}`);
    }
  }
  
  private animate(): void {
    if (this.isGameOver) return;
    
    this.animationFrameId = requestAnimationFrame(() => this.animate());
    
    try {
      const deltaTime = this.clock.getDelta();
      
      // 性能监控日志 - 每10秒输出一次
      const totalTime = this.clock.getElapsedTime();
      if (Math.floor(totalTime) % 10 === 0 && Math.floor(totalTime) > 0) {
        const fps = 1 / deltaTime;
        Debug.perf(`FPS: ${Math.round(fps)}, 对象数: 敌人=${this.enemyTanks.length}, 投射物=${this.projectiles.length}, 爆炸=${this.explosions.length}`);
      }
      
      this.update(deltaTime);
      
      // 更新轨道控制器（如果启用）
      if (this.controls) {
        this.controls.update();
      }
      
      // 更新性能监控
      if (this.performanceMonitor) {
        this.performanceMonitor.update();
      }
      
      this.renderer.render(this.scene, this.camera);
    } catch (error) {
      Debug.error(`动画循环中出错: ${error}`);
      
      // 如果发生错误，我们仍然尝试继续游戏
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
        
        // 尝试在短暂延迟后重新开始动画循环
        setTimeout(() => {
          if (!this.isGameOver) {
            this.animate();
          }
        }, 1000);
      }
    }
  }
  
  private gameOver(): void {
    this.isGameOver = true;
    this.callbacks.onGameOver(this.score);
    Debug.log(`游戏结束，最终得分: ${this.score}`);
    
    // 取消动画循环
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId);
      this.animationFrameId = null;
    }
  }
  
  public resize(width: number, height: number): void {
    try {
      this.camera.aspect = width / height;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(width, height);
      Debug.log(`调整大小: ${width}x${height}`);
    } catch (error) {
      Debug.error(`调整大小时出错: ${error}`);
    }
  }
  
  // 切换调试模式
  public toggleDebugMode(): void {
    this.isDebugMode = !this.isDebugMode;
    if (this.isDebugMode) {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;
      this.controls.maxPolarAngle = Math.PI / 2 - 0.1;
    } else {
      this.controls?.dispose();
      this.controls = null;
    }
    Debug.log(`调试模式: ${this.isDebugMode ? '开启' : '关闭'}`);
  }
  
  // 切换性能监控
  public togglePerformanceMonitor(): void {
    if (this.performanceMonitor) {
      if (this.performanceMonitor.isEnabled === true) {
        this.performanceMonitor.disable();
      } else {
        this.performanceMonitor.enable();
      }
      Debug.log(`性能监控: ${this.performanceMonitor.isEnabled === true ? '开启' : '关闭'}`);
    }
  }
  
  public dispose(): void {
    Debug.log('释放游戏资源');
    
    // 停止动画循环
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId);
      this.animationFrameId = null;
    }
    
    try {
      // 清理所有实体
      this.clearEntities();
      
      // 清理玩家坦克
      if (this.playerTank) {
        this.playerTank.dispose();
        this.playerTank = null;
      }
      
      // 清理地形
      if (this.terrain) {
        this.terrain.dispose();
        this.terrain = null;
      }
      
      // 清理性能监控
      if (this.performanceMonitor) {
        this.performanceMonitor.dispose();
      }
      
      // 移除渲染器
      if (this.renderer && this.renderer.domElement && this.renderer.domElement.parentNode) {
        this.renderer.domElement.parentNode.removeChild(this.renderer.domElement);
      }
      this.renderer.dispose();
      
      Debug.log('游戏资源已释放');
    } catch (error) {
      Debug.error(`释放游戏资源时出错: ${error}`);
    }
  }
} 